/*
 * Copyright 2005-2013 biz-united. All rights reserved.
 * Support: http://www.biz-united.com.cn
 * License: http://www.biz-united.com.cn/?page_id=5&act=3
 */
package net.biz.service.impl;

import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;

import javax.annotation.Resource;
import javax.persistence.LockModeType;

import net.biz.Filter;
import net.biz.Page;
import net.biz.Pageable;
import net.biz.Setting;
import net.biz.Setting.StockAllocationTime;
import net.biz.dao.CartDao;
import net.biz.dao.CartItemDao;
import net.biz.dao.CouponCodeDao;
import net.biz.dao.DepositDao;
import net.biz.dao.MemberDao;
import net.biz.dao.MemberRankDao;
import net.biz.dao.OrderDao;
import net.biz.dao.OrderItemDao;
import net.biz.dao.OrderLogDao;
import net.biz.dao.PaymentDao;
import net.biz.dao.ProductCategoryDao;
import net.biz.dao.ProductDao;
import net.biz.dao.RefundsDao;
import net.biz.dao.ReturnsDao;
import net.biz.dao.ShippingDao;
import net.biz.dao.SnDao;
import net.biz.dto.OrderDTO;
import net.biz.entity.Admin;
import net.biz.entity.Area;
import net.biz.entity.Brand;
import net.biz.entity.Cart;
import net.biz.entity.CartItem;
import net.biz.entity.Coupon;
import net.biz.entity.CouponCode;
import net.biz.entity.Deposit;
import net.biz.entity.GiftItem;
import net.biz.entity.Member;
import net.biz.entity.MemberRank;
import net.biz.entity.Order;
import net.biz.entity.Order.OrderStatus;
import net.biz.entity.Order.PaymentStatus;
import net.biz.entity.Order.ShippingStatus;
import net.biz.entity.OrderItem;
import net.biz.entity.OrderLog;
import net.biz.entity.OrderLog.Type;
import net.biz.entity.Payment;
import net.biz.entity.Payment.Method;
import net.biz.entity.Payment.Status;
import net.biz.entity.PaymentMethod;
import net.biz.entity.Product;
import net.biz.entity.ProductCategory;
import net.biz.entity.Promotion;
import net.biz.entity.Receiver;
import net.biz.entity.Refunds;
import net.biz.entity.Returns;
import net.biz.entity.ReturnsItem;
import net.biz.entity.Shipping;
import net.biz.entity.ShippingItem;
import net.biz.entity.ShippingMethod;
import net.biz.entity.Sn;
import net.biz.service.MemberService;
import net.biz.service.OrderService;
import net.biz.service.StaticService;
import net.biz.util.JsonUtils;
import net.biz.util.ParamsUtil;
import net.biz.util.SettingUtils;

import org.apache.commons.lang.time.DateUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Repository;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.Assert;

import com.home766.dao.OrderRewardDao;
import com.home766.dao.SchemeDao;
import com.home766.dao.ShopsDao;
import com.home766.dao.impl.OrderRewardDaoImpl;
import com.home766.dto.OrderBrandCountDTO;
import com.home766.entity.Dictionary;
import com.home766.entity.Invoice;
import com.home766.entity.OrderReward;
import com.home766.entity.Scheme;
import com.home766.entity.SchemeProduct;
import com.home766.entity.Shops;
import com.home766.service.IDictionaryService;
import com.home766.service.InvoiceService;
import com.home766.service.SchemeProductService;
import com.home766.util.DateTime;
import com.home766.util.StringUtil;

/**
 * Service - 订单
 * 
 * @author BIZ Team
 * @version 3.0
 */
@Service("orderServiceImpl")
public class OrderServiceImpl extends BaseServiceImpl<Order, Long> implements OrderService {

	@Resource(name = "orderDaoImpl")
	private OrderDao orderDao;
	@Resource(name = "orderItemDaoImpl")
	private OrderItemDao orderItemDao;
	@Resource(name = "orderLogDaoImpl")
	private OrderLogDao orderLogDao;
	@Resource(name = "cartDaoImpl")
	private CartDao cartDao;
	@Resource(name = "couponCodeDaoImpl")
	private CouponCodeDao couponCodeDao;
	@Resource(name = "snDaoImpl")
	private SnDao snDao;
	@Resource(name = "memberDaoImpl")
	private MemberDao memberDao;
	@Resource(name = "memberRankDaoImpl")
	private MemberRankDao memberRankDao;
	@Resource(name = "productDaoImpl")
	private ProductDao productDao;
	@Resource(name = "depositDaoImpl")
	private DepositDao depositDao;
	@Resource(name = "paymentDaoImpl")
	private PaymentDao paymentDao;
	@Resource(name = "refundsDaoImpl")
	private RefundsDao refundsDao;
	@Resource(name = "shippingDaoImpl")
	private ShippingDao shippingDao;
	@Resource(name = "returnsDaoImpl")
	private ReturnsDao returnsDao;
	@Resource(name = "staticServiceImpl")
	private StaticService staticService;
	@Resource(name="shopsDaoImpl")
	private ShopsDao shopDao;
	@Resource(name="schemeDaoImpl")
	private SchemeDao schemeDao;
	@Resource(name="schemeProductServiceImpl")
	private SchemeProductService schemeProductService;
	@Resource(name="memberServiceImpl")
	private MemberService memberService;
	@Resource(name="cartItemDaoImpl")
	private CartItemDao cartItemDaoImpl;	
	@Resource(name="invoiceServiceImpl")
	private InvoiceService invoiceService;
	@Resource(name="orderRewardDaoImpl")
	private OrderRewardDao orderRewardDao;
	@Autowired
	private IDictionaryService dictionaryServiceImpl;
	
	@Resource(name="productCategoryDaoImpl")
	private ProductCategoryDao ProductCategoryDaoImpl;
	
	@Resource(name = "orderDaoImpl")
	public void setBaseDao(OrderDao orderDao) {
		super.setBaseDao(orderDao);
	}

	@Transactional(readOnly = true)
	public Order findBySn(String sn) {
		return orderDao.findBySn(sn);
	}

	@Transactional(readOnly = true)
	public List<Order> findList(Member member, Integer count, List<Filter> filters, List<net.biz.Order> orders) {
		return orderDao.findList(member, count, filters, orders);
	}

	@Transactional(readOnly = true)
	public Page<Order> findPage(Member member, Pageable pageable) {
		return orderDao.findPage(member, pageable);
	}

	@Transactional(readOnly = true)
	public Page<Order> findPage(Shops shops, Long adminId, Date beginDate,
			Date endDate, Integer schemeStatus, Integer schemePaymentStatus,
			Integer orderType, OrderStatus orderStatus,
			PaymentStatus paymentStatus, ShippingStatus shippingStatus,
			Boolean hasExpired, Pageable pageable,String shopName,Date createDate,Long provinceId,Long cityId,Long areaId,boolean flag) {
		return orderDao.findPage(shops,adminId,beginDate,endDate,schemeStatus,schemePaymentStatus,orderType,orderStatus, paymentStatus, shippingStatus, hasExpired, pageable,shopName,createDate,provinceId,cityId,areaId,flag);
	}
	
	@Transactional(readOnly = true)
	public List<Order> findExportList(String shopName,Date beginDate,Date endDate,Date createDate,Long provinceId,Long cityId,Long areaId){
		return orderDao.findExportList(shopName,beginDate,endDate,createDate,provinceId,cityId,areaId);
	}

	@Transactional(readOnly = true)
	public Long count(OrderStatus orderStatus, PaymentStatus paymentStatus, ShippingStatus shippingStatus, Boolean hasExpired) {
		return orderDao.count(orderStatus, paymentStatus, shippingStatus, hasExpired);
	}

	@Transactional(readOnly = true)
	public Long waitingPaymentCount(Member member) {
		return orderDao.waitingPaymentCount(member);
	}

	@Transactional(readOnly = true)
	public Long waitingShippingCount(Member member) {
		return orderDao.waitingShippingCount(member);
	}

	@Transactional(readOnly = true)
	public BigDecimal getSalesAmount(Date beginDate, Date endDate) {
		return orderDao.getSalesAmount(beginDate, endDate);
	}

	@Transactional(readOnly = true)
	public Integer getSalesVolume(Date beginDate, Date endDate) {
		return orderDao.getSalesVolume(beginDate, endDate);
	}

	public void releaseStock() {
		orderDao.releaseStock();
	}

	@Value("${default_account}")
	private String ACCOUNT;
	
	
	@Transactional(readOnly = true)
	public Order build(Cart cart, Receiver receiver, PaymentMethod paymentMethod, ShippingMethod shippingMethod, CouponCode couponCode, boolean isInvoice, String invoiceTitle, boolean useBalance, String memo) {
		Assert.notNull(cart);
		Assert.notNull(cart.getMember());
		Assert.notEmpty(cart.getCartItems());

		Order order = new Order();
		order.setShippingStatus(ShippingStatus.unshipped);
		order.setFee(new BigDecimal(0));
		order.setPromotionDiscount(cart.getDiscount());
		order.setCouponDiscount(new BigDecimal(0));
		order.setOffsetAmount(new BigDecimal(0));
		order.setPoint(cart.getEffectivePoint());
		order.setMemo(memo);
		order.setMember(cart.getMember());

		if (receiver != null) {
			order.setConsignee(receiver.getConsignee());
			order.setAreaName(receiver.getAreaName());
			order.setAddress(receiver.getAddress());
			order.setZipCode(receiver.getZipCode());
			order.setPhone(receiver.getPhone());
			order.setArea(receiver.getArea());
		}

		if (!cart.getPromotions().isEmpty()) {
			StringBuffer promotionName = new StringBuffer();
			for (Promotion promotion : cart.getPromotions()) {
				if (promotion != null && promotion.getName() != null) {
					promotionName.append(" " + promotion.getName());
				}
			}
			if (promotionName.length() > 0) {
				promotionName.deleteCharAt(0);
			}
			order.setPromotion(promotionName.toString());
		}

		order.setPaymentMethod(paymentMethod);

		if (shippingMethod != null && paymentMethod != null && paymentMethod.getShippingMethods().contains(shippingMethod)) {
			BigDecimal freight = shippingMethod.calculateFreight(cart.getWeight());
			for (Promotion promotion : cart.getPromotions()) {
				if (promotion.getIsFreeShipping()) {
					freight = new BigDecimal(0);
					break;
				}
			}
			order.setFreight(freight);
			order.setShippingMethod(shippingMethod);
		} else {
			order.setFreight(new BigDecimal(0));
		}

		if (couponCode != null && cart.isCouponAllowed()) {
			couponCodeDao.lock(couponCode, LockModeType.PESSIMISTIC_WRITE);
			if (!couponCode.getIsUsed() && couponCode.getCoupon() != null && cart.isValid(couponCode.getCoupon())) {
				BigDecimal couponDiscount = cart.getEffectivePrice().subtract(couponCode.getCoupon().calculatePrice(cart.getQuantity(), cart.getEffectivePrice()));
				couponDiscount = couponDiscount.compareTo(new BigDecimal(0)) > 0 ? couponDiscount : new BigDecimal(0);
				order.setCouponDiscount(couponDiscount);
				order.setCouponCode(couponCode);
			}
		}
		Integer tempType=null; 
		
		List<OrderItem> orderItems = order.getOrderItems();
//		Scheme scheme=null;
		for (CartItem cartItem : cart.getCartItems()) {
			if (cartItem != null && cartItem.getProduct() != null&&cartItem.getIsSubmit()) {
				if(tempType==null){
					tempType=cartItem.getCartType();
				}
				if(tempType==ParamsUtil.CART_TYPE_NORMAL){
					Product product = cartItem.getProduct();
					OrderItem orderItem = new OrderItem();
					orderItem.setSn(product.getSn());
					orderItem.setOrderType(tempType);
					orderItem.setName(product.getName());
					orderItem.setFullName(product.getFullName());
					orderItem.setPrice(cartItem.getPrice());
					orderItem.setWeight(product.getWeight());
					orderItem.setThumbnail(product.getThumbnail());
					orderItem.setIsGift(false);
					orderItem.setQuantity(cartItem.getQuantity());
					orderItem.setShippedQuantity(0);
					orderItem.setReturnQuantity(0);
					orderItem.setProduct(product);
					orderItem.setOrder(order);
					//设置单体商品下单奖励提成点
					ProductCategory category = product.getProductCategory();
					String str=category.getTreePath();
					String[] array=str.split(",");
					if(array.length>0){
						String categoryId=array[1];
						ProductCategory tempCategory=ProductCategoryDaoImpl.find(Long.parseLong(categoryId));
						category=tempCategory;
					}
					OrderReward reward = orderRewardDao.findByTypeAndCategory(ParamsUtil.CART_TYPE_NORMAL, category == null ? null : category.getId(), product.getBrand());
					orderItem.setRewardPoint(reward == null ? null : reward.getPoint());
					orderItems.add(orderItem);
				}
			}
		}
		order.setOrderType(tempType);
		for (GiftItem giftItem : cart.getGiftItems()) {
			if (giftItem != null && giftItem.getGift() != null) {
				Product gift = giftItem.getGift();
				OrderItem orderItem = new OrderItem();
				orderItem.setSn(gift.getSn());
				orderItem.setName(gift.getName());
				orderItem.setFullName(gift.getFullName());
				orderItem.setPrice(new BigDecimal(0));
				orderItem.setWeight(gift.getWeight());
				orderItem.setThumbnail(gift.getThumbnail());
				orderItem.setIsGift(true);
				orderItem.setQuantity(giftItem.getQuantity());
				orderItem.setShippedQuantity(0);
				orderItem.setReturnQuantity(0);
				orderItem.setProduct(gift);
				orderItem.setOrder(order);
				orderItems.add(orderItem);
			}
		}

		Setting setting = SettingUtils.get();
		if (setting.getIsInvoiceEnabled() && isInvoice) {
			order.setIsInvoice(true);
			order.setInvoiceTitle(invoiceTitle);
			order.setTax(order.calculateTax());
		} else {
			order.setIsInvoice(false);
			order.setTax(new BigDecimal(0));
		}

		if (useBalance) {
			Member member = cart.getMember();
			if (member.getBalance().compareTo(order.getAmount()) >= 0) {
				order.setAmountPaid(order.getAmount());
			} else {
				order.setAmountPaid(member.getBalance());
			}
		} else {
			order.setAmountPaid(new BigDecimal(0));
		}

		if (order.getAmountPayable().compareTo(new BigDecimal(0)) == 0) {
			order.setOrderStatus(OrderStatus.confirmed);
			order.setPaymentStatus(PaymentStatus.paid);
		} else if (order.getAmountPayable().compareTo(new BigDecimal(0)) > 0 && order.getAmountPaid().compareTo(new BigDecimal(0)) > 0) {
			order.setOrderStatus(OrderStatus.confirmed);
			order.setPaymentStatus(PaymentStatus.partialPayment);
		} else {
			order.setOrderStatus(OrderStatus.unconfirmed);
			order.setPaymentStatus(PaymentStatus.unpaid);
		}

		if (paymentMethod != null && paymentMethod.getTimeout() != null && order.getPaymentStatus() == PaymentStatus.unpaid) {
			order.setExpire(DateUtils.addMinutes(new Date(), paymentMethod.getTimeout()));
		}

		return order;
	}
	@Transactional(readOnly = true)
	public Order build(Member member, Receiver receiver, PaymentMethod paymentMethod, ShippingMethod shippingMethod, CouponCode couponCode, boolean isInvoice, String invoiceTitle, boolean useBalance, String memo,Integer orderType,Long schemeId,Long[] ids,Integer schemeArea,Boolean isDissipate,Boolean isTemperature,Boolean isPromote,Boolean isController,String jsonParam) {
		Assert.notNull(orderType);
		Assert.notNull(schemeId);
		Assert.notNull(member);
		Assert.notNull(jsonParam);
		
		Order order = new Order();
		order.setShippingStatus(ShippingStatus.unshipped);
		order.setFee(new BigDecimal(0));
		order.setPromotionDiscount(new BigDecimal(0));//折扣
		order.setCouponDiscount(new BigDecimal(0));
		order.setOffsetAmount(new BigDecimal(0));
		order.setPoint(0L);//积分
		order.setMemo(memo);
		order.setMember(member);
		
		if (receiver != null) {
			order.setConsignee(receiver.getConsignee());
			order.setAreaName(receiver.getAreaName());
			order.setAddress(receiver.getAddress());
			order.setZipCode(receiver.getZipCode());
			order.setPhone(receiver.getPhone());
			order.setArea(receiver.getArea());
		}

		order.setPaymentMethod(paymentMethod);
		
		order.setFreight(new BigDecimal(0));//运费
		
		
		List<OrderItem> orderItems = order.getOrderItems();
		order.setOrderType(orderType);
		
		Scheme scheme=schemeDao.find(schemeId);
		
		Brand rewardBrand=null;
		if(null!=scheme){
			List<SchemeProduct> tempList=scheme.getSchemeProducts();
			List<Map<String,Object>> listMap=jsonToList(jsonParam);
			List<Map<String,Object>> paramsList=getSchemeProducts(listMap,tempList);
			if(tempList!=null&&paramsList!=null){
				for(Map<String,Object> map:paramsList){
					OrderItem orderItem = new OrderItem();
					SchemeProduct sp=(SchemeProduct) map.get("sp");
					Integer quantity=Integer.parseInt(String.valueOf(map.get("quantity")));
					String tempCoefficient=(String) map.get("coefficient");
					BigDecimal price=sp.getPrice();
//					if(!StringUtil.isNullOrSpace(tempCoefficient)){
//						price=new BigDecimal(schemeArea).multiply(new BigDecimal(tempCoefficient)).multiply(price);
//						quantity=1;
//					}
					price=price.setScale(2,BigDecimal.ROUND_HALF_UP);
					Boolean isReward=(Boolean) map.get("isReward");
					if(isReward){
						Long  category=scheme.getType();//方案分类
						//主材勾选了提成点而且主材必须是有提成点
						OrderReward or=	orderRewardDao.findByTypeAndCategory(ParamsUtil.CART_TYPE_SCHEME, category, sp.getBrand());
						if(or!=null){
							if(rewardBrand==null){
								rewardBrand=sp.getBrand();
							}
						}
					}
					orderItem.setSn(sp.getSn());
					orderItem.setOrderType(orderType);
					orderItem.setCoefficient(tempCoefficient==null?null:new BigDecimal(tempCoefficient));
					orderItem.setName(sp.getName());
					orderItem.setFullName(sp.getName());
					orderItem.setPrice(price);
					orderItem.setIsGift(false);
					orderItem.setQuantity(quantity);
					orderItem.setIniQuantity(quantity);
					orderItem.setShippedQuantity(0);
					orderItem.setReturnQuantity(0);
					orderItem.setProduct(null);
					orderItem.setSchemeNameId(sp.getNameId());
					orderItem.setSchemeImage(sp.getImage());
					orderItem.setSchemeProductBrand(sp.getBrand().getName());
					orderItem.setSchemeProductName(sp.getName());
					orderItem.setSchemeProductPrice(sp.getPrice());
//					if(tempCoefficient==null){
//					}else{
//						orderItem.setSchemeProductPrice(price);
//					}
					orderItem.setSchemeProductSn(sp.getSn());
					orderItem.setSchemeProductSpecificationValue(sp.getSpecificationValue().getName());
					orderItem.setOrder(order);
					orderItems.add(orderItem);
				}
			}
			order.setIsController(isController);
			order.setIsTemperature(isTemperature);
			order.setIsDissipate(isDissipate);
			order.setIsPromote(isPromote);
			order.setOutNumber(scheme.getOutNumber());
			order.setInNumber(scheme.getInNumber());
			
			order.setSchemeName(scheme.getName());
			order.setSchemeImage(scheme.getImage());
			order.setPrintCount(0);
			order.setSchemeSn(scheme.getSn());
			//order.setPercent(new BigDecimal(ParamsUtil.ORDER_PAY_PERCENT));//没有首次支付比例了,支付成功才计算支付比例
			order.setIsTehui(scheme.getIsTehui());
			order.setIsChange(scheme.getIsChange());
			order.setBeginArea(scheme.getBeginArea());
			order.setEndArea(scheme.getEndArea());
			if(null==schemeArea){
				order.setSchemeArea(scheme.getAcreage());
			}else{
				order.setSchemeArea(schemeArea);
			}
			if(rewardBrand!=null){
				Long  category=scheme.getType();//方案分类
				OrderReward or=	orderRewardDao.findByTypeAndCategory(ParamsUtil.CART_TYPE_SCHEME, category, rewardBrand);
				order.setRewardPoint(or==null?null:or.getPoint());
			}
			
			order.setShopSchemeArea(0);
			order.setInstallCost(scheme.getInstallCost());//安装费
			order.setAuxiliaryUnitPrice(scheme.getAuxiliaryUnitPrice());//辅材
			order.setSchemePaymentStatus(ParamsUtil.SCHEME_PAYMENT_STATUS_UNPAID);
			order.setSchemeStatus(ParamsUtil.SCHEME_STATUS_STORE);
			order.setSchemeType(scheme.getType());
			BigDecimal schemePrice=order.getAmount();
			
/*			BigDecimal tempPercent= order.getPercent().divide(new BigDecimal(100), 2, BigDecimal.ROUND_HALF_UP);
			BigDecimal customerPay=schemePrice.multiply(tempPercent);
			customerPay=customerPay.divide(new BigDecimal(1),2,BigDecimal.ROUND_HALF_UP);
			BigDecimal shopPay=schemePrice.subtract(customerPay);*/
			order.setPercentPrice(schemePrice);//应支付金额
			//order.setShopShouldPay(shopPay);//没有门店应支付了
			order.setShopPaid(new BigDecimal("0.00"));
			order.setPercentPricePaid(new BigDecimal("0.00"));
			order.setIsCustomerPay(false);
			order.setIsShopPay(false);
		}
		Setting setting = SettingUtils.get();
		if (setting.getIsInvoiceEnabled() && isInvoice) {
			order.setIsInvoice(true);
			order.setInvoiceTitle(invoiceTitle);
			order.setTax(order.calculateTax());
		} else {
			order.setIsInvoice(false);
			order.setTax(new BigDecimal(0));
		}
		
		if (useBalance) {
			if (member.getBalance().compareTo(order.getAmount()) >= 0) {
				order.setAmountPaid(order.getAmount());
			} else {
				order.setAmountPaid(member.getBalance());
			}
		} else {
			order.setAmountPaid(new BigDecimal(0));
		}
		
		if (order.getAmountPayable().compareTo(new BigDecimal(0)) == 0) {
			order.setOrderStatus(OrderStatus.confirmed);
			order.setPaymentStatus(PaymentStatus.paid);
		} else if (order.getAmountPayable().compareTo(new BigDecimal(0)) > 0 && order.getAmountPaid().compareTo(new BigDecimal(0)) > 0) {
			order.setOrderStatus(OrderStatus.confirmed);
			order.setPaymentStatus(PaymentStatus.partialPayment);
		} else {
			order.setOrderStatus(OrderStatus.unconfirmed);
			order.setPaymentStatus(PaymentStatus.unpaid);
		}
		//超时时间
//		if (paymentMethod != null && paymentMethod.getTimeout() != null && order.getPaymentStatus() == PaymentStatus.unpaid) {
//			order.setExpire(DateUtils.addMinutes(new Date(), paymentMethod.getTimeout()));
//		}
		
		return order;
	}
	
	@Transactional
	public Order create(Long shopId,Integer cartType,Cart cart, Receiver receiver, PaymentMethod paymentMethod, ShippingMethod shippingMethod, CouponCode couponCode, boolean isInvoice, String invoiceTitle, boolean useBalance, String memo, Admin operator,Long schemeId,Long[] ids,Integer schemeArea,Invoice invoice,Integer invoiceType,Boolean isDissipate,Boolean isTemperature,Boolean isPromote,Boolean isController,String jsonParam) {
		if(cartType==ParamsUtil.CART_TYPE_NORMAL){
			Assert.notNull(cart);
			Assert.notNull(cart.getMember());
			Assert.notEmpty(cart.getCartItems());
		}
		Assert.notNull(receiver);
		Assert.notNull(paymentMethod);
		Assert.notNull(shippingMethod);
		Order order=null;
		Member member=memberService.getCurrent();
		if(cartType==ParamsUtil.CART_TYPE_NORMAL){
			order = build(cart, receiver, paymentMethod, shippingMethod, couponCode, isInvoice, invoiceTitle, useBalance, memo);
		}else{
			order = build(member, receiver, paymentMethod, shippingMethod, couponCode, isInvoice, invoiceTitle, useBalance, memo,ParamsUtil.CART_TYPE_SCHEME,schemeId,ids,schemeArea, isDissipate, isTemperature, isPromote, isController,jsonParam);
		}
		order.setShippingMethod(shippingMethod);
		order.setShippingMethodName(shippingMethod.getName());
		Shops shop= shopDao.find(shopId);
		order.setSn(snDao.generate(Sn.Type.order));
		order.setShops(shop);
		if (paymentMethod.getMethod() == PaymentMethod.Method.online) {
			order.setLockExpire(DateUtils.addSeconds(new Date(), 20));
			order.setOperator(operator);
		}

		if (order.getCouponCode() != null) {
			couponCode.setIsUsed(true);
			couponCode.setUsedDate(new Date());
			couponCodeDao.merge(couponCode);
		}
		if(cartType==ParamsUtil.CART_TYPE_NORMAL){
			
			for (Promotion promotion : cart.getPromotions()) {
				for (Coupon coupon : promotion.getCoupons()) {
					order.getCoupons().add(coupon);
				}
			}
		}

		Setting setting = SettingUtils.get();
		if (setting.getStockAllocationTime() == StockAllocationTime.order || (setting.getStockAllocationTime() == StockAllocationTime.payment && (order.getPaymentStatus() == PaymentStatus.partialPayment || order.getPaymentStatus() == PaymentStatus.paid))) {
			order.setIsAllocatedStock(true);
		} else {
			order.setIsAllocatedStock(false);
		}
		if(invoice != null){
			invoiceService.save(invoice);
		}
		order.setInvoice(invoice);
		order.setInvoiceType(invoiceType);
		orderDao.persist(order);
		if(invoice != null){
			invoice.setOrderEntity(order);
		}

		OrderLog orderLog = new OrderLog();
		orderLog.setType(Type.create);
		orderLog.setOperator(operator != null ? operator.getUsername() : null);
		orderLog.setOrder(order);
		orderLogDao.persist(orderLog);

		if (order.getAmountPaid().compareTo(new BigDecimal(0)) > 0) {
			memberDao.lock(member, LockModeType.PESSIMISTIC_WRITE);
			member.setBalance(member.getBalance().subtract(order.getAmountPaid()));
			memberDao.merge(member);

			Deposit deposit = new Deposit();
			deposit.setType(operator != null ? Deposit.Type.adminPayment : Deposit.Type.memberPayment);
			deposit.setCredit(new BigDecimal(0));
			deposit.setDebit(order.getAmountPaid());
			deposit.setBalance(member.getBalance());
			deposit.setOperator(operator != null ? operator.getUsername() : null);
			deposit.setMember(member);
			deposit.setOrder(order);
			depositDao.persist(deposit);
		}

		if (setting.getStockAllocationTime() == StockAllocationTime.order || (setting.getStockAllocationTime() == StockAllocationTime.payment && (order.getPaymentStatus() == PaymentStatus.partialPayment || order.getPaymentStatus() == PaymentStatus.paid))) {
			for (OrderItem orderItem : order.getOrderItems()) {
				if (orderItem != null) {
					Product product = orderItem.getProduct();
					productDao.lock(product, LockModeType.PESSIMISTIC_WRITE);
					if (product != null && product.getStock() != null) {
						product.setAllocatedStock(product.getAllocatedStock() + (orderItem.getQuantity() - orderItem.getShippedQuantity()));
						productDao.merge(product);
						orderDao.flush();
						staticService.build(product);
					}
				}
			}
		}

		if(cartType==ParamsUtil.CART_TYPE_NORMAL){
			deleteSubmitCart(cart);
		}
		return order;
	}

	public void update(Order order, Admin operator) {
		Assert.notNull(order);

		Order pOrder = orderDao.find(order.getId());

		if (pOrder.getIsAllocatedStock()) {
			for (OrderItem orderItem : pOrder.getOrderItems()) {
				if (orderItem != null) {
					Product product = orderItem.getProduct();
					productDao.lock(product, LockModeType.PESSIMISTIC_WRITE);
					if (product != null && product.getStock() != null) {
						product.setAllocatedStock(product.getAllocatedStock() - (orderItem.getQuantity() - orderItem.getShippedQuantity()));
						productDao.merge(product);
						orderDao.flush();
						staticService.build(product);
					}
				}
			}
			for (OrderItem orderItem : order.getOrderItems()) {
				if (orderItem != null) {
					Product product = orderItem.getProduct();
					productDao.lock(product, LockModeType.PESSIMISTIC_WRITE);
					if (product != null && product.getStock() != null) {
						product.setAllocatedStock(product.getAllocatedStock() + (orderItem.getQuantity() - orderItem.getShippedQuantity()));
						productDao.merge(product);
						productDao.flush();
						staticService.build(product);
					}
				}
			}
		}

		orderDao.merge(order);

		OrderLog orderLog = new OrderLog();
		orderLog.setType(Type.modify);
		orderLog.setOperator(operator != null ? operator.getUsername() : null);
		orderLog.setOrder(order);
		orderLogDao.persist(orderLog);
	}

	public void confirm(Order order, Admin operator) {
		Assert.notNull(order);

		order.setOrderStatus(OrderStatus.confirmed);
		orderDao.merge(order);

		OrderLog orderLog = new OrderLog();
		orderLog.setType(Type.confirm);
		orderLog.setOperator(operator != null ? operator.getUsername() : null);
		orderLog.setOrder(order);
		orderLogDao.persist(orderLog);
	}

	public void complete(Order order, Admin operator) {
		Assert.notNull(order);

		Member member = order.getMember();
		memberDao.lock(member, LockModeType.PESSIMISTIC_WRITE);

		if (order.getShippingStatus() == ShippingStatus.partialShipment || order.getShippingStatus() == ShippingStatus.shipped) {
			member.setPoint(member.getPoint() + order.getPoint());
			for (Coupon coupon : order.getCoupons()) {
				couponCodeDao.build(coupon, member);
			}
		}

		if (order.getShippingStatus() == ShippingStatus.unshipped || order.getShippingStatus() == ShippingStatus.returned) {
			CouponCode couponCode = order.getCouponCode();
			if (couponCode != null) {
				couponCode.setIsUsed(false);
				couponCode.setUsedDate(null);
				couponCodeDao.merge(couponCode);

				order.setCouponCode(null);
				orderDao.merge(order);
			}
		}

		member.setAmount(member.getAmount().add(order.getAmountPaid()));
/*		if (!member.getMemberRank().getIsSpecial()) {
			MemberRank memberRank = memberRankDao.findByAmount(member.getAmount());
			if (memberRank != null && memberRank.getAmount().compareTo(member.getMemberRank().getAmount()) > 0) {
				member.setMemberRank(memberRank);
			}
		}*/
		memberDao.merge(member);

		if (order.getIsAllocatedStock()) {
			for (OrderItem orderItem : order.getOrderItems()) {
				if (orderItem != null) {
					Product product = orderItem.getProduct();
					productDao.lock(product, LockModeType.PESSIMISTIC_WRITE);
					if (product != null && product.getStock() != null) {
						product.setAllocatedStock(product.getAllocatedStock() - (orderItem.getQuantity() - orderItem.getShippedQuantity()));
						productDao.merge(product);
						orderDao.flush();
						staticService.build(product);
					}
				}
			}
			order.setIsAllocatedStock(false);
		}

		for (OrderItem orderItem : order.getOrderItems()) {
			if (orderItem != null) {
				Product product = orderItem.getProduct();
				productDao.lock(product, LockModeType.PESSIMISTIC_WRITE);
				if (product != null) {
					Integer quantity = orderItem.getQuantity();
					Calendar nowCalendar = Calendar.getInstance();
					Calendar weekSalesCalendar = DateUtils.toCalendar(product.getWeekSalesDate());
					Calendar monthSalesCalendar = DateUtils.toCalendar(product.getMonthSalesDate());
					if (nowCalendar.get(Calendar.YEAR) != weekSalesCalendar.get(Calendar.YEAR) || nowCalendar.get(Calendar.WEEK_OF_YEAR) > weekSalesCalendar.get(Calendar.WEEK_OF_YEAR)) {
						product.setWeekSales((long) quantity);
					} else {
						product.setWeekSales(product.getWeekSales() + quantity);
					}
					if (nowCalendar.get(Calendar.YEAR) != monthSalesCalendar.get(Calendar.YEAR) || nowCalendar.get(Calendar.MONTH) > monthSalesCalendar.get(Calendar.MONTH)) {
						product.setMonthSales((long) quantity);
					} else {
						product.setMonthSales(product.getMonthSales() + quantity);
					}
					product.setSales(product.getSales() + quantity);
					product.setWeekSalesDate(new Date());
					product.setMonthSalesDate(new Date());
					productDao.merge(product);
					orderDao.flush();
					staticService.build(product);
				}
			}
		}

		order.setOrderStatus(OrderStatus.completed);
		order.setExpire(null);
		orderDao.merge(order);

		OrderLog orderLog = new OrderLog();
		orderLog.setType(Type.complete);
		orderLog.setOperator(operator != null ? operator.getUsername() : null);
		orderLog.setOrder(order);
		orderLogDao.persist(orderLog);
	}

	public void cancel(Order order, Admin operator) {
		Assert.notNull(order);

		CouponCode couponCode = order.getCouponCode();
		if (couponCode != null) {
			couponCode.setIsUsed(false);
			couponCode.setUsedDate(null);
			couponCodeDao.merge(couponCode);

			order.setCouponCode(null);
			orderDao.merge(order);
		}

		if (order.getIsAllocatedStock()) {
			for (OrderItem orderItem : order.getOrderItems()) {
				if (orderItem != null) {
					Product product = orderItem.getProduct();
					productDao.lock(product, LockModeType.PESSIMISTIC_WRITE);
					if (product != null && product.getStock() != null) {
						product.setAllocatedStock(product.getAllocatedStock() - (orderItem.getQuantity() - orderItem.getShippedQuantity()));
						productDao.merge(product);
						orderDao.flush();
						staticService.build(product);
					}
				}
			}
			order.setIsAllocatedStock(false);
		}

		order.setOrderStatus(OrderStatus.cancelled);
		order.setExpire(null);
		orderDao.merge(order);

		OrderLog orderLog = new OrderLog();
		orderLog.setType(Type.cancel);
		orderLog.setOperator(operator != null ? operator.getUsername() : null);
		orderLog.setOrder(order);
		orderLogDao.persist(orderLog);
	}

	public void payment(Order order, Payment payment, Admin operator) {
		Assert.notNull(order);
		Assert.notNull(payment);

		orderDao.lock(order, LockModeType.PESSIMISTIC_WRITE);

		payment.setOrder(order);
		paymentDao.merge(payment);
		if (payment.getMethod() == Method.deposit) {
			Member member = order.getMember();
			memberDao.lock(member, LockModeType.PESSIMISTIC_WRITE);
			member.setBalance(member.getBalance().subtract(payment.getAmount()));
			memberDao.merge(member);

			Deposit deposit = new Deposit();
			deposit.setType(operator != null ? Deposit.Type.adminPayment : Deposit.Type.memberPayment);
			deposit.setCredit(new BigDecimal(0));
			deposit.setDebit(payment.getAmount());
			deposit.setBalance(member.getBalance());
			deposit.setOperator(operator != null ? operator.getUsername() : null);
			deposit.setMember(member);
			deposit.setOrder(order);
			depositDao.persist(deposit);
		}

		Setting setting = SettingUtils.get();
		if (!order.getIsAllocatedStock() && setting.getStockAllocationTime() == StockAllocationTime.payment) {
			for (OrderItem orderItem : order.getOrderItems()) {
				if (orderItem != null) {
					Product product = orderItem.getProduct();
					productDao.lock(product, LockModeType.PESSIMISTIC_WRITE);
					if (product != null && product.getStock() != null) {
						product.setAllocatedStock(product.getAllocatedStock() + (orderItem.getQuantity() - orderItem.getShippedQuantity()));
						productDao.merge(product);
						orderDao.flush();
						staticService.build(product);
					}
				}
			}
			order.setIsAllocatedStock(true);
		}

		order.setAmountPaid(order.getAmountPaid().add(payment.getAmount()));
		order.setFee(payment.getFee());
		order.setExpire(null);
		if (order.getAmountPaid().compareTo(order.getAmount()) >= 0) {
			order.setOrderStatus(OrderStatus.confirmed);
			order.setPaymentStatus(PaymentStatus.paid);
		} else if (order.getAmountPaid().compareTo(new BigDecimal(0)) > 0) {
			order.setOrderStatus(OrderStatus.confirmed);
			order.setPaymentStatus(PaymentStatus.partialPayment);
		}
		orderDao.merge(order);

		OrderLog orderLog = new OrderLog();
		orderLog.setType(Type.payment);
		orderLog.setOperator(operator != null ? operator.getUsername() : null);
		orderLog.setOrder(order);
		orderLogDao.persist(orderLog);
	}

	public void refunds(Order order, Refunds refunds, Admin operator) {
		Assert.notNull(order);
		Assert.notNull(refunds);

		orderDao.lock(order, LockModeType.PESSIMISTIC_WRITE);

		refunds.setOrder(order);
		refundsDao.persist(refunds);
		if (refunds.getMethod() == Refunds.Method.deposit) {
			Member member = order.getMember();
			memberDao.lock(member, LockModeType.PESSIMISTIC_WRITE);
			member.setBalance(member.getBalance().add(refunds.getAmount()));
			memberDao.merge(member);

			Deposit deposit = new Deposit();
			deposit.setType(Deposit.Type.adminRefunds);
			deposit.setCredit(refunds.getAmount());
			deposit.setDebit(new BigDecimal(0));
			deposit.setBalance(member.getBalance());
			deposit.setOperator(operator != null ? operator.getUsername() : null);
			deposit.setMember(member);
			deposit.setOrder(order);
			depositDao.persist(deposit);
		}

		order.setAmountPaid(order.getAmountPaid().subtract(refunds.getAmount()));
		order.setExpire(null);
		if (order.getAmountPaid().compareTo(new BigDecimal(0)) == 0) {
			order.setPaymentStatus(PaymentStatus.refunded);
		} else if (order.getAmountPaid().compareTo(new BigDecimal(0)) > 0) {
			order.setPaymentStatus(PaymentStatus.partialRefunds);
		}
		orderDao.merge(order);

		OrderLog orderLog = new OrderLog();
		orderLog.setType(Type.refunds);
		orderLog.setOperator(operator != null ? operator.getUsername() : null);
		orderLog.setOrder(order);
		orderLogDao.persist(orderLog);
	}

	public void shipping(Order order, Shipping shipping, Admin operator) {
		Assert.notNull(order);
		Assert.notNull(shipping);
		Assert.notEmpty(shipping.getShippingItems());

		orderDao.lock(order, LockModeType.PESSIMISTIC_WRITE);

		Setting setting = SettingUtils.get();
		if (!order.getIsAllocatedStock() && setting.getStockAllocationTime() == StockAllocationTime.ship) {
			for (OrderItem orderItem : order.getOrderItems()) {
				if (orderItem != null) {
					Product product = orderItem.getProduct();
					productDao.lock(product, LockModeType.PESSIMISTIC_WRITE);
					if (product != null && product.getStock() != null) {
						product.setAllocatedStock(product.getAllocatedStock() + (orderItem.getQuantity() - orderItem.getShippedQuantity()));
						productDao.merge(product);
						orderDao.flush();
						staticService.build(product);
					}
				}
			}
			order.setIsAllocatedStock(true);
		}

		shipping.setOrder(order);
		shippingDao.persist(shipping);
		for (ShippingItem shippingItem : shipping.getShippingItems()) {
			OrderItem orderItem = order.getOrderItem(shippingItem.getSn());
			if (orderItem != null) {
				Product product = orderItem.getProduct();
				productDao.lock(product, LockModeType.PESSIMISTIC_WRITE);
				if (product != null) {
					if (product.getStock() != null) {
						product.setStock(product.getStock() - shippingItem.getQuantity());
						if (order.getIsAllocatedStock()) {
							product.setAllocatedStock(product.getAllocatedStock() - shippingItem.getQuantity());
						}
					}
					productDao.merge(product);
					orderDao.flush();
					staticService.build(product);
				}
				orderItemDao.lock(orderItem, LockModeType.PESSIMISTIC_WRITE);
				orderItem.setShippedQuantity(orderItem.getShippedQuantity() + shippingItem.getQuantity());
			}
		}
		if (order.getShippedQuantity() >= order.getQuantity()) {
			order.setShippingStatus(ShippingStatus.shipped);
			order.setIsAllocatedStock(false);
		} else if (order.getShippedQuantity() > 0) {
			order.setShippingStatus(ShippingStatus.partialShipment);
		}
		order.setExpire(null);
		orderDao.merge(order);

		OrderLog orderLog = new OrderLog();
		orderLog.setType(Type.shipping);
		orderLog.setOperator(operator != null ? operator.getUsername() : null);
		orderLog.setOrder(order);
		orderLogDao.persist(orderLog);
	}

	public void returns(Order order, Returns returns, Admin operator) {
		Assert.notNull(order);
		Assert.notNull(returns);
		Assert.notEmpty(returns.getReturnsItems());

		orderDao.lock(order, LockModeType.PESSIMISTIC_WRITE);

		returns.setOrder(order);
		returnsDao.persist(returns);
		for (ReturnsItem returnsItem : returns.getReturnsItems()) {
			OrderItem orderItem = order.getOrderItem(returnsItem.getSn());
			if (orderItem != null) {
				orderItemDao.lock(orderItem, LockModeType.PESSIMISTIC_WRITE);
				orderItem.setReturnQuantity(orderItem.getReturnQuantity() + returnsItem.getQuantity());
			}
		}
		if (order.getReturnQuantity() >= order.getShippedQuantity()) {
			order.setShippingStatus(ShippingStatus.returned);
		} else if (order.getReturnQuantity() > 0) {
			order.setShippingStatus(ShippingStatus.partialReturns);
		}
		order.setExpire(null);
		orderDao.merge(order);

		OrderLog orderLog = new OrderLog();
		orderLog.setType(Type.returns);
		orderLog.setOperator(operator != null ? operator.getUsername() : null);
		orderLog.setOrder(order);
		orderLogDao.persist(orderLog);
	}

	@Override
	public void delete(Order order) {
		if (order.getIsAllocatedStock()) {
			for (OrderItem orderItem : order.getOrderItems()) {
				if (orderItem != null) {
					Product product = orderItem.getProduct();
					productDao.lock(product, LockModeType.PESSIMISTIC_WRITE);
					if (product != null && product.getStock() != null) {
						product.setAllocatedStock(product.getAllocatedStock() - (orderItem.getQuantity() - orderItem.getShippedQuantity()));
						productDao.merge(product);
						orderDao.flush();
						staticService.build(product);
					}
				}
			}
		}
		super.delete(order);
	}

	@Override
	public Map<String, Object> updateSchemeStatus(Integer oldStatus,Integer newStatus,Order order,Integer staffType,Admin admin) {
		// TODO Auto-generated method stub
		Map<String, Object> result=new HashMap<String, Object>();
		boolean bool=false;
		Type type=null;
		if(newStatus==ParamsUtil.SCHEME_STATUS_ACCEPTANCE){
			type=Type.headquarters;
		}else if(newStatus==ParamsUtil.SCHEME_STATUS_BALANCE_PAYMENT){
			type=Type.acceptance;
		}else if(newStatus==ParamsUtil.SCHEME_STATUS_CANSEL){
			type=Type.cancel;
		}else if(newStatus==ParamsUtil.SCHEME_STATUS_COMPLETE){
			type=Type.complete;
		}else if(newStatus==ParamsUtil.SCHEME_STATUS_HEADQUARTERS){
			type=Type.pay;
		}else if(newStatus==ParamsUtil.SCHEME_STATUS_PAY){
			type=Type.store;
		}else if(newStatus==ParamsUtil.SCHEME_STATUS_STORE){
			type=Type.create;
		}else if(newStatus==ParamsUtil.SCHEME_STATUS_STORE_BACK_ACCEPTANCE){
			type=Type.backAcceptance;
		}else if(newStatus==ParamsUtil.SCHEME_STATUS_STORE_BACK_HEADQUARTERS){
			type=Type.backHeadquarters;
		}else{
			type=Type.other;
		}
		if(staffType!=ParamsUtil.SCHEME_STAFF_TYPE){
			if(oldStatus==ParamsUtil.SCHEME_STATUS_HEADQUARTERS){
				if(newStatus==ParamsUtil.SCHEME_STATUS_STORE_BACK_HEADQUARTERS){
					bool=true;
				}
			}else if(oldStatus==ParamsUtil.SCHEME_STATUS_ACCEPTANCE){
				if(newStatus==ParamsUtil.SCHEME_STATUS_STORE_BACK_ACCEPTANCE){
					bool=true;	
				}
			}else{
				if(oldStatus!=ParamsUtil.SCHEME_STATUS_COMPLETE||oldStatus!=ParamsUtil.SCHEME_STATUS_CANSEL){
					if(newStatus>oldStatus){
						bool=true;
					}
				}
			}
		}else{
			if(oldStatus!=ParamsUtil.SCHEME_STATUS_COMPLETE||oldStatus!=ParamsUtil.SCHEME_STATUS_CANSEL){
				if(newStatus>oldStatus){
					bool=true;
				}
			}
		}
		if(bool){
			if(order.getSchemeStatus()==ParamsUtil.SCHEME_STATUS_ACCEPTANCE){
				//待验收
				if(order.getSchemePaymentStatus()==ParamsUtil.SCHEME_PAYMENT_STATUS_PAID){
					//全款
					order.setSchemeStatus(ParamsUtil.SCHEME_STATUS_COMPLETE);
				}else{
					//部分，状态为尾款
					order.setSchemeStatus(ParamsUtil.SCHEME_STATUS_BALANCE_PAYMENT);
				}
			}else{
				order.setSchemeStatus(newStatus);
			}
//			Shops shop= order.getServiceShops();
//			if(shop==null||shop.getId()==null){
//				
//			}
//			if(newStatus==ParamsUtil.SCHEME_STATUS_HEADQUARTERS){
//				shop=serviceShop(order.getSn());
//				order.setServiceShops(shop);
//			}
			Order o=update(order);
			OrderLog orderLog = new OrderLog();
			orderLog.setType(type);
			orderLog.setOperator(admin.getName());
			orderLog.setOrder(order);
			orderLogDao.persist(orderLog);
			if(o.getSchemeStatus()==newStatus){
				result.put("type", "success");
			}else{
				result.put("type", "failure");
				result.put("msg", ParamsUtil.SCHEME_STATUS_MSG);
			}
		}
		return result;
	}

	@Override
	public Shops serviceShop(String sn) {
		// TODO Auto-generated method stub
		Order order=orderDao.findBySn(sn);
		Area area=order.getArea();
		Set<Area> set= area.getChildren();
		boolean bool=false;
		if(set==null||set.isEmpty()){
			List<Shops> list= shopDao.getShopsByAreaId(area.getId(),false,ParamsUtil.SHOP_ORDER_BY_TYPE_SCHEME,null,1L);
			Shops s = new Shops();
			for(int i=0;i<list.size();i++){
				s=shopDao.find(list.get(i).getId());
				if(s.getId().longValue()==order.getShops().getId().longValue()){
					//服务门店
					Long lastValue=s.getServiceFrequency();
					if(lastValue==null){
						lastValue=0l;
					}
					s.setServiceFrequency(lastValue + 1l);
					shopDao.merge(s);
					return s;
				}
			}
		}
		if(!bool){
			List<Shops> list= shopDao.getShopsByAreaId(area.getId(),true,ParamsUtil.SHOP_ORDER_BY_TYPE_SCHEME,null,1L);
			if(list!=null&&!list.isEmpty()){
				Shops s=shopDao.find(list.get(0).getId());
				Long lastValue=s.getServiceFrequency();
				if(lastValue==null){
					lastValue=0l;
				}
				s.setServiceFrequency(lastValue + 1l);
				shopDao.merge(s);
				return s;
				//服务门店
			}
			//门店次数 升序 取最小  
			//两个门店相同  次数 按照ID  升序 取最小
		}
		return shopDao.getServiceTotalShops();
	}

	@Override
	public String updateOrderItem(Long id,Long edit) {
		// TODO Auto-generated method stub
		Map<String, Object> result=new HashMap<String, Object>();
		OrderItem oi=orderItemDao.find(id);
		SchemeProduct newSp= schemeProductService.find(edit);//正在替换的主材
		if(newSp!=null&&newSp.getId()!=null){
			BigDecimal tempPrice=new BigDecimal("0.00");//差价
			BigDecimal oldPrice= oi.getPrice();
			BigDecimal newPrice=newSp.getPrice();
			tempPrice=newPrice.subtract(oldPrice);
			
			oi.setShopSchemeImage(newSp.getImage());
			oi.setShopSchemeProductBrand(newSp.getBrand().getName());
			oi.setShopSchemeProductName(newSp.getName());
			oi.setShopSchemeProductPrice(newPrice);
			oi.setShopSchemeProductSn(newSp.getSn());
			oi.setShopSchemeProductSpecificationValue(newSp.getSpecificationValue().getName());
			oi.setDifferencePrice(tempPrice);
			oi.setIsShopAdd(true);
			orderItemDao.updateSchemeProduct(id, true, tempPrice, newSp.getId());
			result.put("type", "success");
		}
		String str=JsonUtils.toJson(result);
		return str;
	}

	@Override
	public int updatePaymentStatus(String sn,BigDecimal price,String paymentOrderId,String orderDatetime,String payDatetime,Admin admin,String C_BANK_SERIAL_NO,String C_CARD_NO) {
		// TODO Auto-generated method stub
		int i=0;
		boolean bool=false;
		int nums = 0;
		Order order=orderDao.findBySn(sn);
		if(order==null){
			sn=sn.substring(0,sn.indexOf("-"));
			order=orderDao.findBySn(sn);
			if(order.getSchemePaymentStatus()!=ParamsUtil.SCHEME_PAYMENT_STATUS_PARTIALPAYMENT){
				order=null;
			}
		}
		Order returnOrder =null;
		if(order!=null){
			Payment pay=new Payment();
			String paySn=snDao.generate(Sn.Type.payment);
			pay.setSn(paySn);
			pay.setAmount(price);
			pay.setCreateDate(DateTime.StringToDateForPay(orderDatetime));
			pay.setMethod(Method.online);
			pay.setOrder(order);
			Member member=order.getMember();
			pay.setPayer(member.getUsername());
			pay.setMember(member);
			pay.setPaymentDate(DateTime.StringToDateForPay(payDatetime));
			pay.setStatus(Status.success);
			pay.setType(Payment.Type.payment);
			pay.setFee(order.getFee());
			pay.setPaymentMethod(order.getPaymentMethodName());
			pay.setAccount(ACCOUNT);
			pay.setPaymentOrderId(paymentOrderId);
			if(order.getOrderType()==ParamsUtil.CART_TYPE_NORMAL){
				if(order.getPaymentStatus()==PaymentStatus.unpaid){
					//单品
					pay.setOperator(ParamsUtil.PAY_FINAL_NAME);
					paymentDao.persist(pay);
					BigDecimal temp= order.getAmountPayable();
					if(temp.compareTo(price)==0){
						order.setPaymentStatus(PaymentStatus.paid);//设置支付状态为已支付
						order.setOrderStatus(OrderStatus.confirmed);
						order.setAmountPaid(price);
						Shops serverShop=order.getServiceShops();
						if(null==serverShop||(serverShop.getId()==null)){
							Shops shop=serviceShopOrder(sn);
							order.setServiceShops(shop);
						}
					}
				}
			}else{
				//方案
				boolean isShopPay=order.getIsShopPay();//是否门店支付
				boolean isCustomerPay=order.getIsCustomerPay();//是否客户支付
				Integer schemeStatus=order.getSchemeStatus();
				order.setPercentPrice(order.getAmount().subtract(price));//应支付累减
				order.setPercentPricePaid(order.getPercentPricePaid().add(price));//已支付金额累加
				if(order.getPaymentTimes()==null){
					order.setPaymentTimes(1);
				}else{
					order.setPaymentTimes(order.getPaymentTimes()+1);//支付次数，累计
				}
				BigDecimal shouldPayMoney = order.getAmountPayable();//应支付
				BigDecimal alreadyPayMoney = order.getPercentPricePaid();//已支付
				BigDecimal amount = order.getAmount();//订单总额
				order.setPercent(alreadyPayMoney.divide(amount,3,BigDecimal.ROUND_HALF_UP).multiply(new BigDecimal("100")));
				//待客户支付，待总部审批，待售后验收，待收尾款状态均可支付
				if(schemeStatus==ParamsUtil.SCHEME_STATUS_PAY || schemeStatus==ParamsUtil.SCHEME_STATUS_HEADQUARTERS 
						|| schemeStatus==ParamsUtil.SCHEME_STATUS_ACCEPTANCE || schemeStatus==ParamsUtil.SCHEME_STATUS_BALANCE_PAYMENT){
					//BigDecimal percentPrice= order.getPercentPrice();//应支付金额
//						BigDecimal temp= percentPrice.multiply(new BigDecimal(ParamsUtil.FLOAT_PERCENTAGE));
//						percentPrice=percentPrice.subtract(temp);
					//客户部分支付，支付状态为部分支付，订单状态为待公司审批
					if(shouldPayMoney.compareTo(new BigDecimal("0"))==1){//支付金额是否在浮动比例之内
						pay.setOperator(ParamsUtil.PAY_FINAL_NAME);
						paymentDao.persist(pay);
						//订单支付状态为 部分支付   客户已经支付  是客户支付 状态改为待公司总部审核
						if(order.getSchemeStatus()==ParamsUtil.SCHEME_STATUS_HEADQUARTERS || order.getSchemeStatus()==ParamsUtil.SCHEME_STATUS_PAY){
							order.setSchemeStatus(ParamsUtil.SCHEME_STATUS_HEADQUARTERS);//订单状态
						}
						order.setSchemePaymentStatus(ParamsUtil.SCHEME_PAYMENT_STATUS_PARTIALPAYMENT);
						System.out.println("------------------部分支付------------------");
						//order.setIsCustomerPay(true);//是客户支付
						//order.setPercentPricePaid(price);//客户支付金额
						//BigDecimal shopPayMoney= order.getAmount().subtract(price);
						//order.setShopShouldPay(shopPayMoney);
						Shops serverShop=order.getServiceShops();
						if(null==serverShop||(serverShop.getId()==null)){
							Shops shop=serviceShop(sn);
							order.setServiceShops(shop);
						}
					}else if(shouldPayMoney.compareTo(new BigDecimal("0"))<=0){//客户全部支付，支付状态为全部支付，订单状态为待公司审批,支付金额可以大于订单总额
						pay.setOperator(ParamsUtil.PAY_FINAL_NAME);
						paymentDao.persist(pay);
						//订单支付状态为 部分支付   客户已经支付  是客户支付 状态改为待公司总部审核
						if(order.getSchemeStatus()==ParamsUtil.SCHEME_STATUS_PAY||order.getSchemeStatus()==ParamsUtil.SCHEME_STATUS_HEADQUARTERS){
							order.setSchemeStatus(ParamsUtil.SCHEME_STATUS_HEADQUARTERS);//订单状态
						}else if(order.getSchemeStatus()==ParamsUtil.SCHEME_STATUS_BALANCE_PAYMENT){
							order.setSchemeStatus(ParamsUtil.SCHEME_STATUS_COMPLETE);//订单状态
						}
						//order.setSchemeStatus(ParamsUtil.SCHEME_STATUS_COMPLETE);//订单状态
						order.setSchemePaymentStatus(ParamsUtil.SCHEME_PAYMENT_STATUS_PAID);//全部支付
						System.out.println("------------------全部支付------------------");
						//order.setIsCustomerPay(true);//是客户支付
						//order.setPercentPricePaid(price);//客户支付金额
						//BigDecimal shopPayMoney= order.getAmount().subtract(price);
						//order.setShopShouldPay(shopPayMoney);
						Shops serverShop=order.getServiceShops();
						if(null==serverShop||(serverShop.getId()==null)){
							Shops shop=serviceShop(sn);
							order.setServiceShops(shop);
						}
					}
				}
/*				if(!isShopPay&&!isCustomerPay){//客户门店均未支付
					
				}else if(!isShopPay&&isCustomerPay){//客户已支付 门店未支付
					if(schemeStatus==ParamsUtil.SCHEME_STATUS_BALANCE_PAYMENT){
						if(null!=admin){
							pay.setOperator(admin.getName());
						}
						paymentDao.persist(pay);
						BigDecimal temp= order.getAmountPayable();//门店须支付金额
						if(temp.compareTo(price)==0){
							order.setSchemeStatus(ParamsUtil.SCHEME_STATUS_COMPLETE);
							order.setSchemePaymentStatus(ParamsUtil.SCHEME_PAYMENT_STATUS_PAID);
							order.setIsShopPay(true);
							order.setShopPaid(price);
						}
					}
				}*/
			}
			returnOrder =update(order);
			if(bool){
				if(admin!=null){
					ACCOUNT=admin.getName();
				}
				OrderLog orderLog = new OrderLog();
				orderLog.setType(Type.payment);
				orderLog.setOperator(ACCOUNT);
				orderLog.setOrder(order);
				orderLogDao.persist(orderLog);
			}
			Shops serverShop=order.getServiceShops();
			if(null==serverShop||(serverShop.getId()==null)){
				orderDao.updateServiceShop(order.getId(), serverShop);
			}
		}
		if(returnOrder!=null){
			return 1;
		}
		return 0;
	}

	@Override
	public Shops serviceShopOrder(String sn) {
		// TODO Auto-generated method stub
		Order order=orderDao.findBySn(sn);
		//收货区域
		Area area=order.getArea();
		Set<Area> set= area.getChildren();
		boolean bool=false;
		if(set==null||set.isEmpty()){
			List<Shops> list= shopDao.getShopsByAreaId(area.getId(),false,ParamsUtil.SHOP_ORDER_BY_TYPE_SINGLE,null,1L);
			Shops s = new Shops();
			for(int i=0;i<list.size();i++){
				s=shopDao.find(list.get(i).getId());
				if(order.getShops()!=null){
					if(s.getId().longValue()==order.getShops().getId().longValue()){
						//服务门店
						Long lastValue=s.getOrdersFrequency();
						if(lastValue==null){
							lastValue=0l;
						}
						s.setOrdersFrequency(lastValue + 1l);
						shopDao.merge(s);
						return s;
					}
				}
			}
		}
		if(!bool){
			List<Shops> list= shopDao.getShopsByAreaId(area.getId(),true,ParamsUtil.SHOP_ORDER_BY_TYPE_SINGLE,null,1L);
			if(list!=null&&!list.isEmpty()){
				Shops s= shopDao.find(list.get(0).getId());
				Long lastValue=s.getOrdersFrequency();
				if(lastValue==null){
					lastValue=0l;
				}
				s.setOrdersFrequency(lastValue + 1l);
				shopDao.merge(s);
				return s;
				//服务门店
			}
			//门店次数 升序 取最小  
			//两个门店相同  次数 按照ID  升序 取最小
		}
		return shopDao.getServiceTotalShops();
	}

	@Override
	public List<OrderDTO> getOrderList(Shops shops,Long adminId,Date beginDate,Date endDate,Integer schemeStatus, Integer orderType,
			OrderStatus orderStatus, PaymentStatus paymentStatus,
			ShippingStatus shippingStatus, Boolean hasExpired,Pageable pageable) {
		// TODO Auto-generated method stub
		List<Order> orderList = orderDao.getOrderList(shops,adminId,beginDate,endDate,schemeStatus, orderType, orderStatus, paymentStatus, shippingStatus, hasExpired,pageable);
		List<OrderDTO> OrderDTOList = new ArrayList<OrderDTO>();
		for(int i = 0;i<orderList.size();i++){
			OrderDTO dto = new OrderDTO();
			try {
				dto.setSn(orderList.get(i).getSn());
				dto.setAmount(orderList.get(i).getAmount());
				dto.setConsignee(orderList.get(i).getConsignee());
				dto.setUserName(orderList.get(i).getMember().getUsername());
				dto.setPaymentMethodName(orderList.get(i).getPaymentMethodName());
				if(orderList.get(i).getShops()!=null){
					dto.setShopsName(orderList.get(i).getShops().getShopsName());
				}
				if(orderList.get(i).getServiceShops()!=null){
					dto.setServiceShopsName(orderList.get(i).getServiceShops().getShopsName());
				}
				dto.setShippingMethodName(orderList.get(i).getShippingMethodName());
				dto.setCareaDate(orderList.get(i).getCreateDate());
			} catch (Exception e) {
				// TODO: handle exception
				e.printStackTrace();
			}
			//orderType==1单品，orderType==2方案
			if(orderType==1){
				//订单状态
				if(orderList.get(i).getOrderStatus()==OrderStatus.unconfirmed){
					dto.setOrderStatus("未确定");
				}else if(orderList.get(i).getOrderStatus()==OrderStatus.confirmed){
					dto.setOrderStatus("已确定");
				}else if(orderList.get(i).getOrderStatus()==OrderStatus.completed){
					dto.setOrderStatus("已完成");
				}else if(orderList.get(i).getOrderStatus()==OrderStatus.cancelled){
					dto.setOrderStatus("已取消");
				}
				//支付状态
				if(orderList.get(i).getPaymentStatus()==PaymentStatus.unpaid){
					dto.setPaymentStatus("未支付");
				}else if(orderList.get(i).getPaymentStatus()==PaymentStatus.partialPayment){
					dto.setPaymentStatus("部分支付");
				}else if(orderList.get(i).getPaymentStatus()==PaymentStatus.paid){
					dto.setPaymentStatus("已支付");
				}else if(orderList.get(i).getPaymentStatus()==PaymentStatus.partialRefunds){
					dto.setPaymentStatus("部分退款");
				}else if(orderList.get(i).getPaymentStatus()==paymentStatus.refunded){
					dto.setPaymentStatus("已退款");
				}
			}else{
				//订单状态
				if(orderList.get(i).getSchemeStatus()==1){
					dto.setOrderStatus("待门店调整");
				}else if(orderList.get(i).getSchemeStatus()==2){
					dto.setOrderStatus("待客户支付");
				}else if(orderList.get(i).getSchemeStatus()==3){
					dto.setOrderStatus("待门店调整(公司退回)");
				}else if(orderList.get(i).getSchemeStatus()==4){
					dto.setOrderStatus("待门店调整(验收退回)");
				}else if(orderList.get(i).getSchemeStatus()==5){
					dto.setOrderStatus("待售后验收");
				}else if(orderList.get(i).getSchemeStatus()==6){
					dto.setOrderStatus("待收尾款");
				}else if(orderList.get(i).getSchemeStatus()==7){
					dto.setOrderStatus("订单结束(完成)");
				}else if(orderList.get(i).getSchemeStatus()==9){
					dto.setOrderStatus("订单结束(取消)");
				}
				
				//支付状态
				if(orderList.get(i).getSchemePaymentStatus()==1){
					dto.setPaymentStatus("未支付");
				}else if(orderList.get(i).getSchemePaymentStatus()==2){
					dto.setPaymentStatus("部分支付");
				}else if(orderList.get(i).getSchemePaymentStatus()==3){
					dto.setPaymentStatus("全部支付");
				}
			}
			//配送状态
			if(orderList.get(i).getShippingStatus().ordinal()==0){
				dto.setShippingStatus("未发货");
			}else if(orderList.get(i).getShippingStatus().ordinal()==1){
				dto.setShippingStatus("部分发货");
			}else if(orderList.get(i).getShippingStatus().ordinal()==2){
				dto.setShippingStatus("已发货");
			}else if(orderList.get(i).getShippingStatus().ordinal()==3){
				dto.setShippingStatus("部分退货");
			}else{
				dto.setShippingStatus("已退货");
			}
			OrderDTOList.add(dto);	
		}
		return OrderDTOList;
	}
	
	/**
	 * 删除购物侧
	 * @param cart
	 */
	private void deleteSubmitCart(Cart cart){
		if(cart!=null){
			Set<CartItem> set=cart.getCartItems();
			if(set!=null&&!set.isEmpty()){
				for(CartItem ci:set){
					if(ci.getIsSubmit()){
						cartItemDaoImpl.remove(ci);
					}
				}
			}
		}
	}
	
	/**
	 * 统计订单中各品牌的数量
	 * @return
	 */
	@Override
	public List<OrderBrandCountDTO> countOrderBrandNumber() {
		return orderDao.countOrderBrandNumber();
	}
	@Override
	public int updateServiceShop(Long id, Shops shops) {
		// TODO Auto-generated method stub
		return orderDao.updateServiceShop(id, shops);
	}
	

	private List<Map<String, Object>> jsonToList(String jsonParam){
		List<Map<String,Object>> list=null;
		if(!StringUtil.isNullOrSpace(jsonParam)){
			list=JsonUtils.toObject(jsonParam, List.class);
		}
		return list;
	}
	private List<Map<String, Object>> getSchemeProducts(List<Map<String, Object>> list,List<SchemeProduct> tempList){
		if(list==null){
			return null;
		}
		List<Map<String, Object>> returnList=null;
		for(Map<String, Object> map:list){
			if(returnList==null){
				returnList=new ArrayList<Map<String,Object>>();
			}
			Long id=Long.parseLong(String.valueOf(map.get("id")));
			SchemeProduct sp=schemeProductService.find(id);
			Map<String, Object> returnMap=new HashMap<String,Object>();
			returnMap.put("id", id);
			returnMap.put("sp",sp);
			returnMap.put("quantity",map.get("quantity"));
			Dictionary dt= dictionaryServiceImpl.find(sp.getNameId());
			List<Dictionary> childrens=dt.getChildrens();
			if(childrens!=null&&childrens.size()>0){
				returnMap.put("coefficient", childrens.get(0).getTitle());
			}
			sp.setIsReward(sp.getIsReward()==null?false:true);
			if(sp.getIsReward()){
				returnMap.put("isReward", true);
			}else{
				returnMap.put("isReward", false);
			}
//			for(SchemeProduct schemeProduct:tempList){
//				if(schemeProduct.getId().longValue()==id.longValue()){
//					
//				}
//			}
			returnList.add(returnMap);
		}
		return returnList;
	}
}